package com.explorex.infra.puma.gateway.netty.ws.message.handler;


import com.explorex.infra.puma.gateway.netty.common.ChannelManager;
import com.explorex.infra.puma.gateway.netty.common.utils.JacksonObjectMapper;
import com.explorex.infra.puma.gateway.netty.ws.WebSocketSession;
import com.explorex.infra.puma.gateway.netty.ws.consts.ChannelConst;
import com.explorex.infra.puma.gateway.netty.ws.enums.MessageTypeEnum;
import com.explorex.infra.puma.gateway.netty.ws.message.Message;
import com.explorex.infra.puma.gateway.netty.ws.message.MessageBody;
import com.explorex.infra.puma.gateway.netty.ws.message.MessageHeader;
import com.explorex.infra.puma.gateway.netty.ws.message.RespMessageBody;
import lombok.Data;

import java.io.Serializable;

/**
 * @author: JacceYang
 * @createTime: 2022/07/15 1:15 下午
 * @description: 消息鉴权处理类
 */
public class BindMessageProcessor implements BaseProcessor {


    @Override
    public short getMessageType() {
        return MessageTypeEnum.BIND.getType();
    }

    @Override
    public Message process(WebSocketSession session, Message messageFrame) {
        BindMessage message = (BindMessage) messageFrame.getBody();
        ChannelManager channelManager = ChannelManager.getInstance();
        session.channel().attr(ChannelConst.TOPIC_KEY).set(message.getTopic());
        if (message.getType() == BindTypeEnum.BIND.value) {
            channelManager.bind(session.channel());
        } else {
            channelManager.unbind(session.channel());
        }
        return buildAck(messageFrame);
    }

    private Message buildAck(Message messageFrame) {
        Message message = new Message();
        MessageHeader header = new MessageHeader(MessageTypeEnum.BIND_ACK.getType());
        header.trackHeader(messageFrame.getHeader());
        message.setHeader(header);
        BindMessageAck ack = new BindMessageAck();
        message.setBody(ack);
        return message;
    }

    public MessageBody parseBody(int contentType, String msgBody) {
        return JacksonObjectMapper.loadObjectUnchecked(msgBody, BindMessage.class);
    }

    enum BindTypeEnum {
        UNBIND(0, "unbind"),
        BIND(1, "bind");

        private final int value;
        private final String desc;

        BindTypeEnum(int value, String desc) {
            this.value = value;
            this.desc = desc;
        }
    }

    @Data
    static class BindMessage implements MessageBody, Serializable {
        // 端侧产生的msg id
        private String mid;
        //topic
        private String topic;
        // 1 - bind 0- unbind
        private int type;
    }

    @Data
    static class BindMessageAck extends RespMessageBody implements Serializable {
        private String mid; // 端侧产生的msg id
        private String token;
    }

}
